﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Cost.Models;
using NBlock.MVCExtensions;
using NBlock.Core;
using NBlock.Core.ORM;
using System.Data.SqlClient;
using Cost.Services;
using System.Linq.Expressions;
using Cost.Services.Services;
using System.Data;
using NBlock.Components.ImportExport;

namespace Cost.Controllers
{
    public class MaterialPurchaseController : Controller
    {
        #region 构造函数
        private readonly ICostRepository<MaterialPurchase> materialPurchaseRepository;
        private readonly ICostRepository<MaterialPurchaseItem> materialPurchaseItemRepository;
        private readonly ICostRepository<MaterialPurchasePlanView> materialPurchasePlanViewRepository;
        private readonly ICostRepository<Material> materialRepository;
        private readonly ICostRepository<Storage> storageRepository;
        private readonly ICostRepository<StockRecord> stockRecordRepository;
        private readonly IEnumService enumService;
        private readonly MaterialService materialService;
        private readonly StorageService storageService;
        private readonly IWordExporter wordExporter;
        public MaterialPurchaseController(ICostRepository<MaterialPurchase> materialpurchaseRepository,
            ICostRepository<MaterialPurchaseItem> materialpurchaseitemRepository,
            ICostRepository<MaterialPurchasePlanView> materialPurchasePlanViewRepository,
            ICostRepository<Storage> storageRepository,
            ICostRepository<StockRecord> stockRecordRepository,
            IEnumService enumService,
            MaterialService materialService,
            ICostRepository<Material> materialRepository,
            StorageService storageService,
            IWordExporter wordExporter)
        {
            this.materialPurchaseRepository = materialpurchaseRepository;
            this.materialPurchaseItemRepository = materialpurchaseitemRepository;
            this.materialPurchasePlanViewRepository = materialPurchasePlanViewRepository;
            this.storageRepository = storageRepository;
            this.stockRecordRepository = stockRecordRepository;
            this.enumService = enumService;
            this.materialRepository = materialRepository;
            this.materialService = materialService;
            this.storageService = storageService;
            this.wordExporter = wordExporter;
        }
        #endregion

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Edit(string Id, string supplierId, DateTime? date)
        {
            var data = materialPurchaseRepository.Find(Id) ?? new MaterialPurchase
            {
                State = "Draft",
                SupplierId = supplierId,
                OrderDate = date,
                Date = date ?? DateTime.Now.AddDays(1),
            };

            // 子表数据
            var items = GetItems(Id, supplierId, date);
            ViewBag.MaterialList = items;

            var sum = items.Sum(m => m.Amount);
            data.TotalAmount = Math.Ceiling(sum.Value * 100) / 100;

            return View(data);
        }

        private List<MaterialPurchaseItem> GetItems(string orderId, string supplierId = "", DateTime? date = null)
        {
            // 从采购计划中产生明细
            if (!string.IsNullOrEmpty(supplierId))
            {
                // 这里的采购数量都是取最小整数，如 4.3 则取 5，已经在视图中做过处理了。
                string[] materialIds = materialService.GetMaterialIdBySupplierId(supplierId, date);
                var list = materialPurchasePlanViewRepository.FindAll(p => p.Date == date && materialIds.Contains(p.Id))
                   .ToList().Select(p => new MaterialPurchaseItem
                   {
                       Id = Guid.NewGuid().ToString(),
                       Code = p.Code,
                       Category = p.Category,
                       MaterialId = p.Id,
                       Name = p.Name,
                       OrderId = "",
                       Amount = p.PurchasePrice,
                       Date = p.Date,
                       OrderCount = p.PurchaseWeight,
                       Price = p.Price,
                       State = "Draft",
                       StorageCount = p.ActualStorage,
                       Unit = p.Unit,
                   }).ToList();

                return list;
            }
            else
            {
                var list = materialPurchaseItemRepository.FindAll(d => d.OrderId == orderId).ToList();
                return list;
            }
        }

        [HttpPost]
        public JsonResult Save(string Id, IList<MaterialPurchaseItem> MaterialList)
        {
            var data = materialPurchaseRepository.Find(Id) ?? new MaterialPurchase();
            TryUpdateModel(data);

            // 如果不是草稿，则不能保存只能查看
            if (data.State != "Draft")
            {
                return Json(new nbAjaxMessage
                {
                    IsSuccess = false,
                    Msg = "订单状态已经不是草稿了，只能查看，不允许保存。"
                });
            }

            if (!string.IsNullOrWhiteSpace(data.SupplierId))
                data.SupplierName = enumService.GetEnumText("Supplier", data.SupplierId);

            var ItemDesc = string.Empty;
            decimal totalAmount = 0;
            // 先删除所有子表，再保持所有子表数据
            materialPurchaseItemRepository.DeleteAll(m => m.OrderId == data.Id);
            if (MaterialList != null)
            {
                foreach (var m in MaterialList)
                {
                    m.OrderId = data.Id;
                    m.State = "Draft";
                    m.Amount = m.Price * m.OrderCount;
                    m.Date = data.Date;
                    m.SupplierId = data.SupplierId;
                    m.SupplierName = data.SupplierName;
                    materialPurchaseItemRepository.Insert(m);

                    // 计算总价格和品名汇总
                    ItemDesc += string.Concat(m.Name, ",");
                    totalAmount += m.Amount == null ? 0 : m.Amount.Value;
                }
            }
            data.ItemDesc = ItemDesc.Trim(',');
            data.TotalAmount = totalAmount;
            materialPurchaseRepository.Save(data);
            return Json(nbAjaxMessage.Successful);
        }

        [HttpPost]
        public JsonResult Delete(string Id)
        {
            materialPurchaseRepository.Delete(Id);
            materialPurchaseItemRepository.DeleteAll(m => m.OrderId == Id);
            return Json(nbAjaxMessage.Successful);
        }

        [HttpPost]
        public JsonResult List(DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            Expression<Func<MaterialPurchase, bool>> filter = null;
            if (date.HasValue)
            {
                filter = p => p.Date == date;
            }

            var pageData = materialPurchaseRepository.GetPageable(pager, filter, where);
            var data = pager.ToGridData(pageData);
            return Json(data);
        }

        #region 订货
        [HttpPost]
        public JsonResult Delivery(string Id)
        {
            var ids = Id.Split(',');
            var Purchases = materialPurchaseRepository.FindAll(p => ids.Contains(p.Id)).ToList();
            foreach (var p in Purchases)
            {
                p.State = "Delivery";
                materialPurchaseRepository.Update(p);
                //查找所有明细数据
                var itemList = materialPurchaseItemRepository.FindAll(m => m.OrderId == p.Id).ToList();
                foreach (var m in itemList)
                {
                    m.State = "Delivery";
                    materialPurchaseItemRepository.Update(m);
                }
            }

            return Json(nbAjaxMessage.Successful);
        }
        #endregion

        #region 入库
        public ActionResult Storage(string Id)
        {
            var data = materialPurchaseRepository.Find(Id);
            if (data.State != "Delivery")
            {
                throw new Exception(string.Format("当前订单（{0}）的状态不是订单，所以无法入库！", Id));
            }

            // 子表数据
            var items = GetItems(Id);
            items.ForEach(item =>
            {
                // 设置默认的入库数量
                item.StorageCount = item.StorageCount ?? item.OrderCount;
            });
            ViewBag.detail = items;

            return View(data);
        }

        [HttpPost]
        public JsonResult Storage(string Id, IList<MaterialPurchaseItem> detail)
        {
            var data = materialPurchaseRepository.Find(Id);
            data.State = "Storage";
            materialPurchaseRepository.Save(data);

            decimal totalAmount = 0;

            // 先删除所有子表，再保持所有子表数据
            materialPurchaseItemRepository.DeleteAll(m => m.OrderId == data.Id);
            foreach (var m in detail)
            {
                m.OrderId = data.Id;
                m.State = "Storage";
                m.Amount = m.Price * m.StorageCount;
                m.Date = data.Date;
                m.SupplierId = data.SupplierId;
                m.SupplierName = data.SupplierName;
                materialPurchaseItemRepository.Insert(m);

                totalAmount += m.Amount == null ? 0 : m.Amount.Value;

                storageService.StorageIn(m.MaterialId, m.StorageCount.Value, "采购入库");
            }
            data.TotalAmount = totalAmount;

            return Json(nbAjaxMessage.Successful);
        }
        #endregion

        #region 采购计划
        public ActionResult Plan()
        {
            return View();
        }

        [HttpPost]
        public JsonResult PlanList(string supplierId, DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            string[] materialIds = materialService.GetMaterialIdBySupplierId(supplierId, date);
            Expression<Func<MaterialPurchasePlanView, bool>> filter = m => materialIds.Contains(m.Id);
            if (date.HasValue)
                filter = filter.And(m => m.Date == date);

            var list = materialPurchasePlanViewRepository.GetPageable(pager, filter, where);
            var fdata = pager.ToGridData(list);
            return Json(fdata);
        }

        [HttpPost]
        public JsonResult PlanTree(string Id)
        {
            var list = new List<nbJsonTreeNode>();
            if (string.IsNullOrWhiteSpace(Id))
            {
                // 获取供应商的数据
                var items = enumService.GetEnumDataSource("Supplier");
                foreach (var item in items)
                {
                    list.Add(new nbJsonTreeNode
                    {
                        id = item.Value,
                        text = item.Text,
                        value = item.Value
                    });
                }
            }
            return Json(list);
        }
        #endregion

        #region 打印采购单
        public FileResult Export(string Id)
        {
            var ds = new DataSet();
            var ids = Id.Split(',');
            var purchases = materialPurchaseRepository.FindAll(p => ids.Contains(p.Id)).ToList();
            var materials = materialPurchaseItemRepository.FindAll(item => ids.Contains(item.OrderId)).ToList();
            ds.AddNestedList(purchases, materials, p => p.Id, c => c.OrderId, "Purchase", "Materials");

            var data = wordExporter.ExportPDF(ds, Server.MapPath("~/Upload/Templates/Purchase.doc"), e =>
            {
                if (e.FieldName == "Unit")
                    e.Text = enumService.GetEnumText("MaterialUnit", e.FieldValue.ToString());
            });

            return File(data, "Application/pdf");
        }

        public FileResult ExportWord(string Id)
        {
            var ds = new DataSet();
            var ids = Id.Split(',');
            var purchases = materialPurchaseRepository.FindAll(p => ids.Contains(p.Id)).ToList();
            var materials = materialPurchaseItemRepository.FindAll(item => ids.Contains(item.OrderId)).ToList();
            ds.AddNestedList(purchases, materials, p => p.Id, c => c.OrderId, "Purchase", "Materials");

            var data = wordExporter.ExportWord(ds, Server.MapPath("~/Upload/Templates/Purchase.doc"), e =>
            {
                if (e.FieldName == "Unit")
                    e.Text = enumService.GetEnumText("MaterialUnit", e.FieldValue.ToString());
            });

            return File(data, "Application/word", string.Format("采购单_{0:yyyy-MM-dd}.doc", DateTime.Now));
        }
        #endregion

        #region 采购明细
        public ActionResult Detail()
        {
            return View();
        }

        [HttpPost]
        public JsonResult DetailList(string state, DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            Expression<Func<MaterialPurchaseItem, bool>> filter = null;
            if (date.HasValue)
            {
                filter = filter.And(p => p.Date == date);
            }
            if (!string.IsNullOrEmpty(state))
            {
                filter = filter.And(p => p.State == state);
            }

            var pageData = materialPurchaseItemRepository.GetPageable(pager, filter, where);
            var data = pager.ToGridData(pageData);
            return Json(data);
        }
        #endregion
    }
}
